package jhunter.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jhunter.conf.entities.vo.Entity;
import jhunter.conf.entities.vo.Property;
import jhunter.conf.entities.vo.Relationship;
import jhunter.dao.bo.BaseObject;
import jhunter.dao.type.TypeHandlerFactory;

public class EntityExt {

	private EntityContainer entityContainer;

	private Entity entity;

	private String primaryProp;

	private List<String> properties = new ArrayList<String>();

	private Map<String, Property> propsMap = new HashMap<String, Property>();

	private List<String> relationships = new ArrayList<String>();

	/**
	 * 引用
	 */
	private List<String> refRelationships = new ArrayList<String>();

	private Map<String, Relationship> relationshipsMap = new HashMap<String, Relationship>();

	/**
	 * key ukname value proplist
	 * 
	 * @return
	 */
	private Map<String, List<String>> uniqueMap = new HashMap<String, List<String>>();

	public EntityExt(EntityContainer entityContainer, Entity entity) {
		this.entity = entity;
		this.entityContainer = entityContainer;
		for (Property prop : entity.getProperties().getProperty()) {
			propsMap.put(prop.getName(), prop);
			properties.add(prop.getName());
			if (prop.getType().equals("id")) {
				primaryProp = prop.getName();
			}
			String ukName = prop.getUniqueName();
			if (ukName != null && !ukName.equals("")) {
				ukName = "uk_" + entity.getTableName() + "_" + ukName;// 注意oracle
																		// 有长度限制
																		// TODO
				if (this.uniqueMap.get(ukName) == null) {
					this.uniqueMap.put(ukName, new ArrayList<String>());
				}
				uniqueMap.get(ukName).add(prop.getName());
			}
		}
		if (entity.getRelationships() != null) {
			for (Relationship rel : entity.getRelationships().getRelationship()) {
				relationshipsMap.put(rel.getName(), rel);
				relationships.add(rel.getName());
				if (!rel.isToMany()) {
					refRelationships.add(rel.getName());
				}
			}
		}
	}

	/**
	 * like "customer_number" would match a "customerNumber" property name.
	 * 
	 * @param name
	 * @return
	 */
	public static String convertUnderscoreNameToPropertyName(String name) {
		StringBuilder result = new StringBuilder();
		boolean nextIsUpper = false;
		if (name != null && name.length() > 0) {
			if ((name.startsWith("t_") || name.startsWith("T_")) && name.length() > 2) {
				name = name.substring(2);
			}
			if (name.length() > 1 && name.substring(1, 2).equals("_")) {
				result.append(name.substring(0, 1).toUpperCase());
			} else {
				result.append(name.substring(0, 1).toLowerCase());
			}
			for (int i = 1; i < name.length(); i++) {
				String s = name.substring(i, i + 1);
				if (s.equals("_")) {
					nextIsUpper = true;
				} else {
					if (nextIsUpper) {
						result.append(s.toUpperCase());
						nextIsUpper = false;
					} else {
						result.append(s.toLowerCase());
					}
				}
			}
		}
		return result.toString();
	}

	public String getTableAlias() {
		String ta = this.entity.getTableAlias();
		if (ta == null || ta.length() == 0) {
			ta = convertUnderscoreNameToPropertyName(this.getTableName());
		}
		return ta;
	}

	public String getColumnName(String propName) {
		Property pro = propsMap.get(propName);
		String column = pro.getColumnName();
		if (column == null || column.trim().length() == 0) {
			column = propName;
		}
		return column;
	}

	public List<String> getColumns() {
		List<String> list = new ArrayList<String>(properties.size());
		for (String p : properties) {
			list.add(getColumnName(p));
		}
		return list;
	}

	public Entity getEntity() {
		return entity;
	}

	public void setEntity(Entity entity) {
		this.entity = entity;
	}

	public String getId() {
		return entity.getId();
	}

	public Map<String, Property> getPropsMap() {
		return propsMap;
	}

	public void setPropsMap(Map<String, Property> propsMap) {
		this.propsMap = propsMap;
	}

	public EntityContainer getEntityContainer() {
		return entityContainer;
	}

	public void setEntityContainer(EntityContainer entityContainer) {
		this.entityContainer = entityContainer;
	}

	public Map<String, Relationship> getRelationshipsMap() {
		return relationshipsMap;
	}

	public void setRelationshipsMap(Map<String, Relationship> relationshipsMap) {
		this.relationshipsMap = relationshipsMap;
	}

	public List<String> getProperties() {
		return properties;
	}

	public List<String> getNamedProperties() {
		List<String> list = new ArrayList<String>();
		for (String p : properties) {
			list.add(":" + p);
		}
		return list;
	}

	public void setProperties(List<String> properties) {
		this.properties = properties;
	}

	public String getTableName() {
		return entity.getTableName();
	}

	public String getPrimaryProp() {
		return primaryProp;
	}

	public void setPrimaryProp(String primaryProp) {
		this.primaryProp = primaryProp;
	}

	public List<String> getRelationships() {
		return relationships;
	}

	public void setRelationships(List<String> relationships) {
		this.relationships = relationships;
	}

	public List<String> getRefRelationships() {
		return refRelationships;
	}
	
	public BaseObject getMappingInstanceObject() {
		//TODO
		return new BaseObject();
	}

	public void setRefRelationships(List<String> refRelationships) {
		this.refRelationships = refRelationships;
	}

	public String getHibernateTypeName(String prop) {
		Property p = this.getPropsMap().get(prop);
		return TypeHandlerFactory.getTypeHandler(p.getType()).getHibernateTypeName();
	}

	public int getColumnLength(String prop) {
		Property p = this.getPropsMap().get(prop);
		String length = p.getLength();
		if (length != null) {
			return Integer.valueOf(length);
		}
		return 255;
	}

	public Map<String, List<String>> getUniqueMap() {
		return uniqueMap;
	}

	public EntityExt getRefEntity(String targetId) {
		return this.entityContainer.getEntityExt(targetId);
	}

}
